/****************************************************************************
**
**	File Name   : MainDlg.cpp
**
**	Project     : DatChecker
**
**	Last Updated: $Header: /DatChecker.root/DatChecker/MainDlg.cpp 8     2/27/04 8:56a Neusel $
**
**	Description : 
**
**		Implementation of the CMainDlg class.
**
****************************************************************************/
#include "stdafx.h"
#include "MainDlg.h"
#include "AboutDlg.h"

#include "ObjCloneDlg.h"
#include "ObjInfoDlg.h"
#include "ObjViewDlg.h"

#include "Zipper.h"
#include "Unzipper.h"

#pragma comment(lib, "ZipUnzip\\zlib\\zlibstat.lib")
/*	----------------------------------------------------------------------
	Local Structures/Declarations
	----------------------------------------------------------------------	*/
static const LPCTSTR	kZipFilename	= _T("DatChecker Archive.zip");

static enum	LIST_COLUMNS
			{
			COL_STATUS = 0,
			COL_AUTHOR,
			COL_FILE_NAME,
			COL_OBJ_NAME,
			COL_OBJ_TYPE,
			COL_OBJ_SIZE,
			COL_OBJ_MD5,
			COL_DETAILS,
			COL_COUNT
			};

#define	COL_FIRST	COL_STATUS
#define	COL_LAST	COL_DETAILS
/*	----------------------------------------------------------------------
	Global Constants/Variables
	----------------------------------------------------------------------	*/
extern Options			theOptions;
/*	----------------------------------------------------------------------
	Local Function Prototypes
	----------------------------------------------------------------------	*/

/****************************************************************************
**
**	CMainDlg::HandleDroppedFile() -- handles a dropped file
**
*/
BOOL
CMainDlg::HandleDroppedFile(
	LPCTSTR		pszFile)
{
if (GOOD_PTR(pszFile) && strlen(pszFile) > 0)
	{
	CAtlFile	file;
	CWaitCursor	waiter;

	ATLTRACE("CMainDlg::HandleDroppedFile() => %s\n", pszFile);
	//
	//	Now examine the object and add it to the list
	//
	bool			bOK;
	ObjInfo			objInfo = { 0 };
	CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );

	if (!ctrlList.IsWindow())
		return FALSE;

	strncpy(objInfo.szFile, pszFile, MAX_PATH);
	if (file.Create(objInfo.szFile, GENERIC_READ, 0, OPEN_EXISTING) == S_OK)
		{
		bOK = ExamineObject(file, objInfo);
		file.Close();

		if (bOK)
			{
			ObjInfoPtr		pOI;
			int				nItem;

			nItem = ctrlList.GetItemCount();
			
			while (--nItem >= 0)
				{
				pOI = reinterpret_cast<ObjInfoPtr>( ctrlList.GetItemData(nItem) );

				if (GOOD_PTR(pOI) && 
					StrCmpPartial(pOI->szFile, pszFile, false) == CSTR_EQUAL)
					{
					removeObject(pOI);
					break;
					}
				}

			addObject(objInfo);
			}
		else
			{
			CString	strMsg;
			
			strMsg.Format(_T("Ignoring dropped file \"%s\"."), pszFile);
			(void) ::MessageBox(m_hWnd, LPCTSTR(strMsg), kStrAppTitle, 
								MB_OK|MB_ICONSTOP);
			}
		}
	}

return TRUE;	// return TRUE to continue to next dropped file
}	/* end of CMainDlg::HandleDroppedFile() */
/****************************************************************************
**
**	CMainDlg::addObject() -- adds an object to the list
**
*/
void
CMainDlg::addObject(
	ObjInfo const &		objNew)
{
//
//	Add the object to the list
//
ObjInfoPtr		pOI = new ObjInfo;

if (NULL_PTR(pOI))
	{
	ATLTRACE(_T("Couldn't create ObjInfo object.\n"));
	return;
	}
	
*pOI = objNew;
//
//	Update the list
//
CString			str;
LPTSTR			pstr;
LVITEM			item;
int				nItem = 0;
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );

::ZeroMemory(&item, sizeof(LVITEM));
//
//	Status
//
item.iItem		= INT_MAX;
item.mask		= LVIF_IMAGE|LVIF_PARAM;
item.iImage		= pOI->nFlag;
item.lParam		= LPARAM(pOI);
if ((nItem = ctrlList.InsertItem(&item)) < 0)
	return;

// (void) ctrlList.SetItemData(nItem, DWORD(pOINew));

if ((pstr = strrchr(pOI->szFile, _T('\\'))) == NULL)
	pstr = pOI->szFile;
else
	pstr++;
	
item.iItem		= nItem;
item.iSubItem	= COL_FILE_NAME;
item.mask		= LVIF_TEXT;
item.pszText	= pstr;
(void) ctrlList.SetItem(&item);
//
//	Author
//		
switch (pOI->author)
	{
	case OA_RCT2:		item.pszText = _T("RCT2");		break;
	case OA_RCT2_WW:	item.pszText = _T("WW");		break;
	case OA_RCT2_TT:	item.pszText = _T("TT");		break;
	case OA_CUSTOM:		item.pszText = _T("custom");	break;
	default:	// OA_UNKNOWN			
		item.pszText = _T("??");		
		break;
	}
	
if (item.pszText)
	{
	item.mask		= LVIF_TEXT;
	item.iSubItem	= COL_AUTHOR;
	(void) ctrlList.SetItem(&item);
	}
//
//	Object Name
//
item.iSubItem	= COL_OBJ_NAME;
item.mask		= LVIF_TEXT;
item.pszText	= pOI->szName;
(void) ctrlList.SetItem(&item);
//
//	Object Type
//
switch (pOI->type)
	{
	case OT_RIDE_SHOP:	item.pszText = _T("Ride/Shop");			break;
	case OT_SM_SCENERY:	item.pszText = _T("Small Scenery");		break;
	case OT_LG_SCENERY:	item.pszText = _T("Large Scenery");		break;
	case OT_WALLS:		item.pszText = _T("Walls");				break;
	case OT_BANNERS:	item.pszText = _T("Banners");			break;
	case OT_PATHS:		item.pszText = _T("Paths");				break;
	case OT_PATH_ITEMS:	item.pszText = _T("Path Items");		break;
	case OT_GROUP:		item.pszText = _T("Scenery Group");		break;
	case OT_ENTRANCE:	item.pszText = _T("Park Entrance");		break;
	case OT_WATER:		item.pszText = _T("Water");				break;
	case OT_SC6_TEXT:	item.pszText = _T("Scenario Text");		break;
	default:			item.pszText = _T("(unknown type)");	break;	
	}

if (item.pszText)
	{
	item.mask		= LVIF_TEXT;
	item.iSubItem	= COL_OBJ_TYPE;
	(void) ctrlList.SetItem(&item);
	}
//
//	Object size
//
item.iSubItem	= COL_OBJ_SIZE;
item.mask		= LVIF_TEXT;
item.pszText	= StrNum(pOI->sDataLen);
(void) ctrlList.SetItem(&item);
//
//	Object MD5
//
item.iSubItem	= COL_OBJ_MD5;
item.mask		= LVIF_TEXT;
item.pszText	= (LPTSTR) MD5::ConvertToASCII(pOI->digest);
(void) ctrlList.SetItem(&item);
str.UnlockBuffer();
//
//	Object Details
//
if (strlen(pOI->szInfo) > 0)
	{
	item.iSubItem	= COL_DETAILS;
	item.mask		= LVIF_TEXT;
	item.pszText	= pOI->szInfo;
	(void) ctrlList.SetItem(&item);
	}
}	/* end of CMainDlg::addObject() */
/****************************************************************************
**
**	CMainDlg::deleteObjFile() -- deletes all object information
**
*/
bool
CMainDlg::deleteObjFile(
	ObjInfoPtr	pOI)
{
if (NULL_PTR(pOI))
	return false;
	
if (DeleteFile(pOI->szFile))
	removeObject(pOI);	// the file is gone, so remove the item from the list as well.
else
	{
	CString	strMsg;
	
	strMsg.Format(_T("Could not delete %s."), pOI->szFile);
	(void) ::MessageBox(m_hWnd, LPCTSTR(strMsg), kStrAppTitle, 
						MB_OK|MB_ICONSTOP);
	return false;
	}

return true;
}	/* end of deleteObjFile() */
/****************************************************************************
**
**	CMainDlg::discardData() -- deletes all object information
**
*/
void
CMainDlg::discardData(void)
{
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );

if (ctrlList.IsWindow())
	{
	ObjInfoPtr	pOI;
	int			nItem = ctrlList.GetItemCount();

	ATLTRACE(_T("Deleting %d ObjInfo items\n"), nItem);
	
	while (--nItem >= 0)
		{
		pOI = reinterpret_cast<ObjInfoPtr>( ctrlList.GetItemData(nItem) );
		ctrlList.SetItemData(nItem, 0);
		
		ATLASSERT( GOOD_PTR(pOI) );
		delete pOI;
		}
	}
	
ctrlList.DeleteAllItems();
}	/* end of CMainDlg::discardData() */
/****************************************************************************
**
**	CMainDlg::onBrowse() -- WMU_BROWSE command handler
**
*/
LRESULT				
CMainDlg::onBrowse(
	UINT		, 
	WPARAM		, 
	LPARAM		lParam, 
	BOOL &		)
{
BROWSEINFO		bi = { 0 };
LPITEMIDLIST	pidl = NULL;
LRESULT			lResult = FALSE;
LPTSTR			psz = LPTSTR(lParam);

ATLASSERT( !::IsBadStringPtr(psz, MAX_PATH) );

bi.lpszTitle	= _T("ObjData Folder Location");
bi.hwndOwner	= m_hWnd;

pidl = SHBrowseForFolder(&bi);
if (pidl)
	{
	IMalloc *	pIMalloc = NULL;
	
	if (SHGetPathFromIDList(pidl, psz))	// get the name of the folder
		lResult = TRUE;
		
	if (SUCCEEDED( SHGetMalloc(&pIMalloc) ))
		{
		pIMalloc->Free(pidl);
		pIMalloc->Release();
		}
	}

return lResult;
}	/* end of CMainDlg::onBrowse() */
/****************************************************************************
**
**	CMainDlg::onCheckObjects() 
**
*/
void
CMainDlg::onCheckObjects(void)
{
TCHAR			szMask[MAX_PATH+1] = { 0 };
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );

ATLASSERT( ctrlList.GetViewType() == LVS_REPORT );

if (m_ctrlBrowser.IsWindow() &&
	m_ctrlBrowser.GetWindowText(szMask, MAX_PATH) > 0)
	{
	CFindFile	finder;

	(void) strncpy(theOptions.szObjDataPath, szMask, MAX_PATH);
	if (finder.FindFile(strncat(szMask, _T("\\*.DAT"), MAX_PATH)))
		{
		discardData();
		m_bScanning = true;
		ScanObjectFolder(++m_sequence, m_hWnd, szMask);
		}
	else
		{
		(void) ::MessageBox(m_hWnd, _T("No object (*.DAT) files found."),
							kStrAppTitle, MB_OK|MB_ICONASTERISK);
		}
	}
}	/* end of MainDlg::onCheckObjects() */
/****************************************************************************
**
**	CMainDlg::onCommand() -- WM_COMMAND message handler
**
*/
LRESULT				
CMainDlg::onCommand(
	WORD		, 
	WORD		wID, 
	HWND		, 
	BOOL &		bMsgHandled)
{
LRESULT	lResult;

lResult = bMsgHandled = TRUE;

switch (wID)
	{
	case ID_CHECK:
		onCheckObjects();
		break;
	
	case ID_FILE_DELETE:
		onObjDelete();
		break;
	
	case ID_OBJ_ARCHIVE:
		onObjArchive();
		break;
	
	case ID_OBJ_CLONE:
		onObjClone();
		break;
	
	case ID_OBJ_REMOVE:
		onObjRemove();
		break;
	
	case ID_OBJ_VIEW:
		onObjView();
		break;
		
	case ID_PROPERTIES:
		onProperties();
		break;
			
	case IDCANCEL:
	case IDOK:
		lResult = bMsgHandled = FALSE;
		(void) GetWindowRect(&theOptions.rMainDlg);

		DestroyWindow();
		::PostQuitMessage(wID);
		break;
		
	default:
		lResult = bMsgHandled = FALSE;
	}

return lResult;
}	/* end of CMainDlg::onCommand() */
/****************************************************************************
**
**	CMainDlg::onContextMenu() -- WM_CONTEXTMENU message handler
**
*/
void
CMainDlg::onContextMenu(
	HWND			,
	CPoint			ptHit)
{
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );

ATLTRACE(_T("CMainDlg::onContextMenu()\n")); 

if (ctrlList.GetSelectedIndex() >= 0)	
	{
	CRect	rClient;
	CMenu	hMenu,
			hMenuPopup;

	GetClientRect(&rClient); 
	ScreenToClient(&ptHit);
	if (PtInRect(&rClient, ptHit) &&
		hMenu.LoadMenu(IDM_CONTEXT))
		{
		CMenu	hMenuPopup = hMenu.GetSubMenu(0);
		
		ClientToScreen(&ptHit);
		ATLASSERT( hMenuPopup.IsMenu() );
		::SetMenuDefaultItem(hMenuPopup, ID_OBJ_VIEW, FALSE);
		hMenuPopup.TrackPopupMenu(	TPM_LEFTALIGN|TPM_RIGHTBUTTON, 
									ptHit.x, ptHit.y, m_hWnd); 
		} 
	else
		SetMsgHandled(FALSE);
	}
else
	::MessageBeep(MB_ICONASTERISK);	// acknowledge the mouse click
}	/* end of CMainDlg::onContextMenu() */
/****************************************************************************
**
**	CMainDlg::onCopyData() -- WM_COPYDATA message handler
**
*/
LRESULT
CMainDlg::onCopyData(
	HWND			,
	PCOPYDATASTRUCT	pCDS)
{
if (NULL_PTR(pCDS))
	return FALSE;
//
//	Check the "sequence number"
//
if (pCDS->dwData != m_sequence)
	{
	ATLTRACE(_T("Ignoring out-of-sequence object.\n"));
	return TRUE;
	}
//
//	Extract the object information from the message
//
ATLASSERT( GOOD_PTR(pCDS->lpData) );
ATLASSERT(pCDS->cbData == sizeof(ObjInfo));

addObject(*reinterpret_cast<ObjInfoPtr>( pCDS->lpData ));

return TRUE;
}	/* end of CMainDlg::onCopyData() */
/****************************************************************************
**
**	CMainDlg::onEndScan() -- WMU_END_SCAN command handler
**
*/
LRESULT				
CMainDlg::onEndScan(
	UINT		, 
	WPARAM		, 
	LPARAM		lParam, 
	BOOL &		)
{
if (m_sequence == lParam)
	{
	CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );
	
	if (ctrlList.IsWindow())
		{
		for (int ndx = COL_FIRST; ndx < COL_LAST; ++ndx)
			ctrlList.SetColumnWidth(ndx, LVSCW_AUTOSIZE);

		if (COL_LAST > COL_FIRST)
			ctrlList.SetColumnWidth(COL_LAST, LVSCW_AUTOSIZE_USEHEADER);
		}
		
	m_bScanning = false;
	}

return TRUE;
}	/* end of CMainDlg::onEndScan() */
/****************************************************************************
**
**	CMainDlg::onHeaderDividerDblClick() -- HDN_DIVIDERDBLCLICK notification handler
**
*/
LRESULT 
CMainDlg::onHeaderDividerDblClick(
	int			, 
	LPNMHDR		pnmh, 
	BOOL &		)
{
int				nWidth;
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );
NMHEADER *		pNMH = reinterpret_cast<NMHEADER *>( pnmh );

if (NULL_PTR(pNMH) || !ctrlList.IsWindow())
	return 0;

nWidth = (pNMH->iItem < COL_LAST) ?	LVSCW_AUTOSIZE : LVSCW_AUTOSIZE_USEHEADER;
ctrlList.SetColumnWidth(pNMH->iItem, nWidth);

#ifdef	_DEBUG
	ATLTRACE(	_T("Column #%d has a width of %d\n"), 
				pNMH->iItem, ctrlList.GetColumnWidth(pNMH->iItem));
#endif

return 0;
}	/* end of CMainDlg::onHeaderDividerDblClick() */
/****************************************************************************
**
**	CMainDlg::onHeaderItemClick() -- HDN_ITEMCLICK notification handler
**
*/
LRESULT 
CMainDlg::onHeaderItemClick(
	int		idCtrl, 
	LPNMHDR	pnmh, 
	BOOL &	bHandled)
{
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );
NMHEADER *		pNMH = reinterpret_cast<NMHEADER *>( pnmh );

if (NULL_PTR(pNMH) || !ctrlList.IsWindow())
	return 0;
//
//	Set the sorted column to the column that was just clicked.  If we're
//	already sorting on that column, reverse the sort order.
//	
if (pNMH->iItem == m_nSortedColumn)
	m_bDescending = !m_bDescending;
else
	{
	m_bDescending = false;
	m_nSortedColumn = pNMH->iItem;
	}
//
//	Adjust the header to reflect the sort status
//
#if (_WIN32_WINNT >= 0x501)
HDITEM			hdi;
CHeaderCtrl		ctrlHeader = ctrlList.GetHeader();

for (int nCol = 0; nCol < COL_COUNT; ++nCol)
	{
	hdi.mask	= HDI_FORMAT;
	if (!ctrlHeader.GetItem(nCol, &hdi))
		continue;
		
	if (nCol == m_nSortedColumn)
		{
		hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
		hdi.fmt |= m_bDescending ? HDF_SORTDOWN : HDF_SORTUP;
		(void) ctrlHeader.SetItem(nCol, &hdi);
		}
	else if (hdi.fmt & (HDF_SORTDOWN|HDF_SORTUP))
		{
		hdi.fmt &= ~(HDF_SORTDOWN|HDF_SORTUP);
		(void) ctrlHeader.SetItem(nCol, &hdi);
		}
	}
#endif

ATLTRACE(	_T("Sort column #%ld %s.\n"), 
			m_nSortedColumn, (m_bDescending ? "DESCENDING" : "ASCENDING"));

ctrlList.SortItems(CMainDlg::fnCmp, LPARAM(this));

return 0;
}	/* end of CMainDlg::onHeaderItemClick() */
/****************************************************************************
**
**	CMainDlg::onItemDblClick() -- NM_DBLCLK notification handler
**
*/
LRESULT 
CMainDlg::onItemDblClick(
	int		idCtrl, 
	LPNMHDR	pnmh, 
	BOOL &	bHandled)
{
CListViewCtrl	ctrlList( GetDlgItem(IDC_LIST) );
NMHEADER *		pNMH = reinterpret_cast<NMHEADER *>( pnmh );

if (GOOD_PTR(pNMH) &&
	(ctrlList.GetSelectedIndex() == pNMH->iItem || ctrlList.SelectItem(pNMH->iItem)))
	{	
	onObjView();
	}

return 0;	// not used
}	/* end of CMainDlg::onItemDblClick() */
/****************************************************************************
**
**	CMainDlg::onInitDialog() -- WM_INITDIALOG message handler
**
*/
LRESULT				
CMainDlg::onInitDialog(HWND, LPARAM)
{
DlgResize_Init();
PlaceWindow(*this, theOptions.rMainDlg);
SetWindowText(kStrAppTitle);
//
//	Load icons
//
HICON		hIcon;

hIcon = (HICON)::LoadImage(	_Module.GetResourceInstance(), 
							MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 
							::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), 
							LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
hIcon = (HICON)::LoadImage(	_Module.GetResourceInstance(), 
							MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 
							::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 
							LR_DEFAULTCOLOR);
SetIcon(hIcon, FALSE);
//
//	Add our About... item to the system menu
//
ATLASSERT((ID_APP_ABOUT & 0xFFF0) == ID_APP_ABOUT);
ATLASSERT(ID_APP_ABOUT < 0xF000);

CMenu	menuSys = GetSystemMenu(FALSE);

if (menuSys.IsMenu())
    menuSys.AppendMenu(MF_STRING, ID_APP_ABOUT, _T("About..."));
//
m_ctrlBrowser.SubclassWindow( GetDlgItem(IDC_FILE_BROWSER) );
m_ctrlBrowser.SetWindowText( theOptions.szObjDataPath );
//
//	Initialize the List window.  The column widths are hardcoded and arbitrary as hell.
//
LVCOLUMN		column;
CListViewCtrl	ctrlList = GetDlgItem(IDC_LIST);

ATLASSERT( ctrlList.IsWindow() );
ATLASSERT( ctrlList.GetViewType() == LVS_REPORT );
ATLASSERT( (GetStyle() & LVS_SINGLESEL) != 0 );

::ZeroMemory(&column, sizeof(LVCOLUMN));

column.mask		= LVCF_FMT|LVCF_WIDTH;
column.fmt		= LVCFMT_LEFT;
column.cx		= 32;
ctrlList.InsertColumn(COL_STATUS, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_CENTER;
column.pszText	= _T("Source");
column.cx		= 24;
ctrlList.InsertColumn(COL_AUTHOR, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_LEFT;
column.pszText	= _T("File");
column.cx		= 80;
ctrlList.InsertColumn(COL_FILE_NAME, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_LEFT;
column.pszText	= _T("Name");
column.cx		= 64;
ctrlList.InsertColumn(COL_OBJ_NAME, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_LEFT;
column.pszText	= _T("Type");
column.cx		= 80;
ctrlList.InsertColumn(COL_OBJ_TYPE, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_RIGHT;
column.pszText	= _T("Size");
column.cx		= 48;
ctrlList.InsertColumn(COL_OBJ_SIZE, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT|LVCF_WIDTH;
column.fmt		= LVCFMT_LEFT;
column.pszText	= _T("MD5 Hash");
column.cx		= 256;
ctrlList.InsertColumn(COL_OBJ_MD5, &column);	

column.mask		= LVCF_FMT|LVCF_TEXT;
column.fmt		= LVCFMT_LEFT;
column.pszText	= _T("Details");
ctrlList.InsertColumn(COL_DETAILS, &column);	

ctrlList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
//
//	Set the image list for the list control, building the 256 color image 
//	list the hard way, because CImageList::Create() is brain-damaged...
//
CBitmap		bmFlags;
CImageList	imgFlags;

if (bmFlags.LoadBitmap(IDB_FLAGS) &&
	imgFlags.Create(24, 24, ILC_COLOR8|ILC_MASK, FLAG_COUNT, 1) &&
	imgFlags.Add(bmFlags, RGB(0xFF,0x00,0xFF)) >= 0)	// returns -1 on failure
	{
	ATLASSERT( imgFlags.GetImageCount() == FLAG_COUNT );
	ctrlList.SetImageList(imgFlags, LVSIL_SMALL);
	}
//	
//	Register object for message filtering and idle updates
//
CMessageLoop *	pLoop = _Module.GetMessageLoop();

ATLASSERT(pLoop != NULL);

pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);

UIAddChildWindowContainer(m_hWnd);

return TRUE;
}	/* end of CMainDlg::onInitDialog() */
/****************************************************************************
**
**	CMainDlg::onObjArchive()	-- 
**
*/
void
CMainDlg::onObjArchive(void)
{
CString		strMsg;
LPCTSTR		pstrName;
ObjInfoPtr	pOI = getSelectedObject();

if (NULL_PTR(pOI))
	return;
//
//	Use just the filename for messages for brevity
//
pstrName = strrchr(pOI->szFile, '\\');
if (GOOD_PTR(pstrName))
	pstrName++;
else
	pstrName = pOI->szFile;

ATLASSERT( GOOD_PTR(pstrName) );
ATLASSERT( strlen(pstrName) > 0 );
//
//	If this is a commercially-released object, make the user shoot his/her own foot.
//
if (IS_RCT2(pOI->author))
	{
	strMsg.Format(_T("Are you sure you want to archive the object \"%s\"?"), pstrName);
	if (AtlMessageBox(	m_hWnd,
						LPCTSTR(strMsg), _T("Confirm Archive"), 
						MB_YESNO|MB_ICONQUESTION) != IDYES)
		{
		return;
		}
	}
//
//	OK...rock and roll time.
//
CUnzipper	unzip;
bool		bDelete = false,
			bExists = false,
			bFound	= false;

if (unzip.OpenZip(kZipFilename))
	{
	bExists = true;
	bFound = unzip.GotoFile(pstrName);
	unzip.CloseZip();
	}

if (bFound)
	bDelete = true;
else
	{
	CZipper		zip;
	
	if (zip.OpenZip(kZipFilename, NULL, bExists))
		{
		if (zip.AddFileToZip(pOI->szFile, true))
			bDelete = true;
		else
			{
			strMsg.Format(	_T("Could not add \"%s\" to archive file \"%s\"."), 
							pstrName, kZipFilename);
			(void) AtlMessageBox(	m_hWnd,
									LPCTSTR(strMsg), _T("Archive Failed!"),
									MB_OK|MB_ICONSTOP);
			}
			
		zip.CloseZip();
		}
	else
		{
		strMsg.Format(_T("Could not create archive file \"%s\"."), kZipFilename);
		(void) AtlMessageBox(	m_hWnd,
								LPCTSTR(strMsg), _T("Archive Failed!"),
								MB_OK|MB_ICONSTOP);
		}
	}
	
if (bDelete && deleteObjFile(pOI))
	pOI = NULL;
}	/* end of onObjArchive() */
/****************************************************************************
**
**	CMainDlg::onObjClone()	-- ID_OBJ_CLONE command handler
**
*/
void
CMainDlg::onObjClone(void)
{
ObjInfoPtr	pOI = getSelectedObject();

if (GOOD_PTR(pOI))
	{
	CObjClone	dlgObjClone(*pOI);	
	
	if (dlgObjClone.DoModal() == IDOK)
		onCheckObjects();	// rescan the current directory
	}
}	/* end of onObjClone() */
/****************************************************************************
**
**	CMainDlg::onObjDelete()	-- 
**
*/
void
CMainDlg::onObjDelete(void)
{
CString		strMsg;
ObjInfoPtr	pOI = getSelectedObject();

if (NULL_PTR(pOI))
	return;
	
strMsg.Format(_T("Are you sure you want to delete the object file \"%s\"?"),
				pOI->szFile);
			
if (AtlMessageBox(	m_hWnd, 
					LPCTSTR(strMsg), _T("Confirm File Deletion"),
					MB_YESNO|MB_ICONQUESTION) == IDYES)
	{
	if (IS_RCT2(pOI->author) ||
		AtlMessageBox(	m_hWnd,
						_T("This file is part of RCT2 or an expansion pack. Are you REALLY sure you want to delete it?"),
						_T("Confirm File Deletion"), 
						MB_YESNO|MB_ICONQUESTION) == IDYES)
		{
		(void) deleteObjFile(pOI);		//	OK, user really wants to do this...
		}
	}
}	/* end of onObjDelete() */
/****************************************************************************
**
**	CMainDlg::onObjRemove()	-- 
**
*/
void
CMainDlg::onObjRemove(void)
{
removeObject( getSelectedObject() );
}	/* end of onObjRemove() */
/****************************************************************************
**
**	CMainDlg::onObjView()	-- ID_OBJ_VIEW command handler
**
*/
void
CMainDlg::onObjView(void)
{
ObjInfoPtr	pOI = getSelectedObject();

if (GOOD_PTR(pOI))
	{
	if (pOI->nImages > 0)
		{
		CObjViewDlg	dlgObjView(*pOI);	
		(void) dlgObjView.DoModal();
		}
	else
		{
		(void) AtlMessageBox(NULL, 
							_T("This object does not have any images associated with it."), 
							kStrAppTitle);
		}
	}
}	/* end of onObjView() */
/****************************************************************************
**
**	CMainDlg::onProperties()	-- ID_PROPERTIES command handler
**
*/
void
CMainDlg::onProperties(void)
{
ObjInfoPtr	pOI = getSelectedObject();

if (GOOD_PTR(pOI))
	{
	CObjInfoDlg		dlgObjInfo(*pOI);	
	
	(void) dlgObjInfo.DoModal();
	}
}	/* end of onProperties() */
/****************************************************************************
**
**	CMainDlg::onSysCommand()	-- WM_SYSCOMMAND message handler
**
*/
LRESULT				
CMainDlg::onSysCommand(
	UINT	uid, 
	CPoint	)
{
if ((uid & 0xFFF0) == ID_APP_ABOUT)
	{
	CAboutDlg		dlgAbout;
	
	(void) dlgAbout.DoModal();
	}
else
	SetMsgHandled(FALSE);
	
return TRUE;
}	/* end of CMainDlg::onSysCommand() */	
/****************************************************************************
**
**	CMainDlg::removeObject() -- removes an object item from the list
**
*/
void
CMainDlg::removeObject(
	ObjInfoPtr	pOI)
{
CListViewCtrl	ctrlList = GetDlgItem(IDC_LIST);

if (GOOD_PTR(pOI) && ctrlList.IsWindow())
	{
	int			nItem;
	LVFINDINFO	lvFindInfo = { 0 };
	
	ATLTRACE("CMainDlg::removeObject() => \"%s\"\n", pOI->szName);
	
	lvFindInfo.lParam	= DWORD(pOI);
	lvFindInfo.flags	= LVFI_PARAM;

	if ((nItem = ctrlList.FindItem(&lvFindInfo, -1)) >= 0)
		{
		ctrlList.DeleteItem(nItem);
		delete pOI;
		}
	}
}	/* end of CMainDlg::removeObject() */	
/****************************************************************************
**
**	CMainDlg::fnCmp() -- [STATIC] 
**
*/
int CALLBACK
CMainDlg::fnCmp(
	LPARAM		lParam1,
	LPARAM		lParam2,
	LPARAM		lParam3)
{
int			nCmp = 0;
CMainDlg *	pDlg = reinterpret_cast<CMainDlg *>( lParam3 );

if (GOOD_PTR(pDlg))
	{
	CListViewCtrl	ctrlList( pDlg->GetDlgItem(IDC_LIST) );
	ObjInfoPtr		poiLHS = reinterpret_cast<ObjInfoPtr>( lParam1 ),
					poiRHS = reinterpret_cast<ObjInfoPtr>( lParam2 ); 
	
	if (NULL_PTR(poiLHS) || NULL_PTR(poiRHS) || !ctrlList.IsWindow())
		return 0;
	
	switch (pDlg->m_nSortedColumn)
		{
		case COL_STATUS:
			if (poiLHS->nFlag != poiRHS->nFlag)
				nCmp = poiLHS->nFlag - poiRHS->nFlag;
			break;
		case COL_AUTHOR:
			nCmp = int(poiLHS->author) - int(poiRHS->author);
			break;
		case COL_FILE_NAME:
			nCmp = _strcmpi(poiLHS->szFile, poiRHS->szFile);
			break;
		case COL_OBJ_NAME:
			nCmp = _strcmpi(poiLHS->szName, poiRHS->szName);
			break;
		case COL_OBJ_TYPE:
			nCmp = int(poiLHS->type) - int(poiRHS->type);
			break;
		case COL_OBJ_SIZE:
			if (poiLHS->sDataLen != poiRHS->sDataLen)
				nCmp = (poiLHS->sDataLen < poiRHS->sDataLen) ? -1 : 1;
			break;
		case COL_OBJ_MD5:
			nCmp = MD5::Compare(poiLHS->digest, poiRHS->digest);
			break;
		case COL_DETAILS:
			nCmp = _strcmpi(poiLHS->szInfo, poiRHS->szInfo);
			break;
		}
		
	if (pDlg->m_bDescending)
		nCmp = -nCmp;
	}
	
return nCmp;
}	/* end of CMainDlg::fnCmp() */
/****************************************************************************
**
**	$History: MainDlg.cpp $
 * 
 * *****************  Version 8  *****************
 * User: Neusel       Date: 2/27/04    Time: 8:56a
 * Updated in $/DatChecker.root/DatChecker
 * v1.9 -- Added drag and drop handler.
 * 
 * *****************  Version 7  *****************
 * User: Neusel       Date: 1/21/04    Time: 6:40p
 * Updated in $/DatChecker.root/DatChecker
 * 
 * *****************  Version 6  *****************
 * User: Neusel       Date: 1/20/04    Time: 12:08p
 * Updated in $/DatChecker.root/DatChecker
 * v1.7 -- rearranged Properties dialog and added yellow flags.
 * 
 * *****************  Version 5  *****************
 * User: Neusel       Date: 12/31/03   Time: 3:23p
 * Updated in $/DatChecker.root/DatChecker
 * v1.5 -- made "View..." the default object action.
 * 
 * *****************  Version 4  *****************
 * User: Neusel       Date: 12/17/03   Time: 8:58a
 * Updated in $/DatChecker.root/DatChecker
 * 
 * *****************  Version 3  *****************
 * User: Neusel       Date: 9/08/03    Time: 9:34a
 * Updated in $/DatChecker.root/DatChecker
 * v1.2 -- added ObjData header file and internal checks.
 * 
 * *****************  Version 2  *****************
 * User: Neusel       Date: 8/14/03    Time: 3:59p
 * Updated in $/DatChecker.root/DatChecker
 * Added "Object Clone" and String Table capability.
 * 
 * *****************  Version 1  *****************
 * User: Neusel       Date: 8/14/03    Time: 9:25a
 * Created in $/DatChecker.root/DatChecker
**
**	-------------------------------------------------------------------------
**
**	End of MainDlg.cpp
**
****************************************************************************/
